/**
 * 全局菜单
 */
JEditor.ToolMenu = {};

JEditor.ToolMenu.getContainer = function() {
    var c = document.getElementById("je-menu-panel");

    if(c == null) {
        c = document.createElement("div");
        c.id = "je-menu-panel";
        c.className = "je-panel";
        document.body.appendChild(c);
    }
    return c;
};

JEditor.ToolMenu.getForm = function() {
    var a = {};
    var p = this.getContainer();
    JEditor.wrap(a, p.getElementsByTagName("input"));
    JEditor.wrap(a, p.getElementsByTagName("radio"));
    JEditor.wrap(a, p.getElementsByTagName("checkbox"));
    JEditor.wrap(a, p.getElementsByTagName("select"));
    return a;
};

JEditor.ToolMenu.getPosition = function(e) {
    var x = e.offsetLeft;
    var y = e.offsetTop;
    var parent = e.offsetParent;

    while(true) {
        if(parent == null || parent == document.body) {
            break;
        }

        x = x + parent.offsetLeft;
        y = y + parent.offsetTop;
        parent = parent.offsetParent;
    }
    return {"x": x, "y": y};
};

JEditor.ToolMenu.show = function(editor, command, html) {
    var e = editor.getTool(command);

    editor.bookmark = editor.getBookmark();
    com.skin.util.StyleUtil.addClass(e, "active");
    e.focus();

    var c = this.getContainer();
    var position = this.getPosition(e);

    this.hide();
    c.innerHTML = html;
    c.setAttribute("editorId", editor.instanceId);
    c.setAttribute("command", command);
    c.style.top = (position.y + 28) + "px";
    c.style.left = position.x + "px";
    c.style.display = "block";
};

JEditor.ToolMenu.hide = function() {
    var c = this.getContainer();
    var editor = this.getEditor();
    var command = c.getAttribute("command");

    if(editor != null && command != null) {
        var tool = editor.getTool(command);

        if(tool != null) {
            com.skin.util.StyleUtil.removeClass(tool, "active");
        }
    }

    c.style.display = "none";
    c.removeAttribute("editorId");
    c.removeAttribute("command");
    c.innerHTML = "";
};

JEditor.ToolMenu.showColorMenu = function(editor, command) {
    var b = [];
    var m = [
            "ffffff", "000000", "eeece1", "1f497d", "4f81bd", "c0504d", "9bbb59", "8064a2", "4bacc6", "f79646",
            "f2f2f2", "7f7f7f", "ddd9c3", "c6d9f0", "dbe5f1", "f2dcdb", "ebf1dd", "e5e0ec", "dbeef3", "fdeada",
            "d8d8d8", "595959", "c4bd97", "8db3e2", "b8cce4", "e5b9b7", "d7e3bc", "ccc1d9", "b7dde8", "fbd5b5",
            "bfbfbf", "3f3f3f", "938953", "548dd4", "95b3d7", "d99694", "c3d69b", "b2a2c7", "92cddc", "fac08f",
            "a5a5a5", "262626", "494429", "17365d", "366092", "953734", "76923c", "5f497a", "31859b", "e36c09",
            "7f7f7f", "0c0c0c", "1d1b10", "0f243e", "244061", "632423", "4f6128", "3f3151", "205867", "974806",
            "c00000", "ff0000", "ffc000", "ffff00", "92d050", "00b050", "00b0f0", "0070c0", "002060", "7030a0"];

    b[b.length] = "<div style=\"clear: both; height: 24px;\">";
    b[b.length] =     "<div id=\"je-cp-preview\" class=\"je-cp-preview\" unselectable=\"on\"></div>";
    b[b.length] =     "<div class=\"je-cp-clear\"unselectable=\"on\" onclick=\"JEditor.ToolMenu.execute('" + command + "', 'transparent');\">清空颜色</div>";
    b[b.length] = "</div>";
    b[b.length] = "<div class=\"je-cp-label\">主题颜色</div>";

    for(var i = 0; i < 6; i++) {
        b[b.length] = "<div class=\"je-color-panel\" onmouseover=\"JEditor.ToolMenu.setColor(event)\">";

        for(var j = 0; j < 10; j++) {
            var k = i * 10 + j;
            b[b.length] = "<a class=\"je-cp-box\" style=\"background-color: #" + m[k] + ";\" data-color=\"" + m[k] + "\" tabindex=\"0\" title=\"" + m[k] + "\" href=\"javascript:void(0)\" onclick=\"JEditor.ToolMenu.execute('" + command + "', '#" + m[k] + "');\"></a>";
        }
        b[b.length] = "</div>";
    }

    b[b.length] = "<div class=\"je-cp-label\">标准颜色</div>";
    b[b.length] = "<div class=\"je-color-panel\" onmouseover=\"JEditor.ToolMenu.setColor(event)\">";

    for(var j = 0; j < 10; j++) {
        var k = 6 * 10 + j;
        b[b.length] = "<a class=\"je-cp-box\" style=\"background-color: #" + m[k] + ";\" data-color=\"" + m[k] + "\" tabindex=\"0\" title=\"" + m[k] + "\" href=\"javascript:void(0)\" onclick=\"JEditor.ToolMenu.execute('" + command + "', '#" + m[k] + "');\"></a>";
    }
    b[b.length] = "</div>";
    b[b.length] = "</div>";

    var html = com.skin.util.StringUtil.replace(b.join(""), editor.i18n);
    JEditor.ToolMenu.show(editor, command, html);
};

JEditor.ToolMenu.setColor = function(event) {
    var src = (event.srcElement || event.target);

    if(src.className != "je-cp-box") {
        return;
    }
    document.getElementById("je-cp-preview").style.backgroundColor = "#" + src.getAttribute("data-color");
};

JEditor.ToolMenu.getEditor = function() {
    var c = this.getContainer();
    var id = c.getAttribute("editorId");
    return JEditor.getInstance(id);
};

JEditor.ToolMenu.execute = function(command) {
    var editor = this.getEditor();

    if(editor != null) {
        var tool = JEditor.tools[command];

        if(tool != null && tool.execute != null) {
            var args = [editor].concat([].slice.call(arguments, 1));
            tool.execute.apply(tool, args);
        }
    }
    this.hide();
};

/**
 * 菜单翻页
 */
JEditor.ScrollPage = {};
JEditor.ScrollPage.scroll = function(src) {
    var pageId = src.getAttribute("pageId");

    if(pageId != null) {
        var list = src.parentNode.childNodes;

        for(var i = 0; i < list.length; i++) {
            if(list[i].nodeType == 1) {
                var temp = list[i].getAttribute("pageId");

                if(temp != null) {
                    list[i].className = "";
                }
            }
        }

        list = src.parentNode.parentNode.childNodes;

        for(var i = 0; i < list.length; i++) {
            if(list[i].nodeType == 1) {
                var temp = list[i].getAttribute("pageId");

                if(temp != null) {
                    if(temp != pageId) {
                        list[i].style.display = "none";
                    }
                    else {
                        list[i].style.display = "block";
                    }
                }
            }
        }
        src.className = "active";
    }
};

(function() {
    var LinkMenu = JEditor.LinkMenu = {};

    LinkMenu.getMenu = function() {
        var c = document.getElementById("je-link-menu");

        if(c == null) {
            c = document.createElement("div");
            c.id = "je-link-menu";
            c.className = "je-link-menu";
            c.innerHTML = "<input id=\"je-link-input\" class=\"link\" spellcheck=\"false\" value=\"\"/>"
                + "<div id=\"je-link-ensure\" class=\"je-btn\">确定</div>"
                + "<div id=\"je-link-remove\" class=\"je-btn\">删除</div>";
            document.body.appendChild(c);

            com.skin.util.EventUtil.addListener(document.getElementById("je-link-ensure"), "click", function() {
                var src = LinkMenu.element;

                if(src != null) {
                    var name = src.getAttribute("name");
                    var href = src.getAttribute("href");
                    var value = document.getElementById("je-link-input").value;

                    if(name != null) {
                        src.setAttribute("name", value);
                    }
                    else {
                        src.setAttribute("href", value);
                    }
                }
                LinkMenu.hide(true);
            });

            com.skin.util.EventUtil.addListener(document.getElementById("je-link-remove"), "click", function() {
                var src = LinkMenu.element;

                if(src != null) {
                    src.parentNode.removeChild(src);
                }
                LinkMenu.hide(true);
            });
        }
        return c;
    };

    LinkMenu.show = function(src, top, left) {
        var menu = this.getMenu();
        var name = src.getAttribute("name");
        var href = src.getAttribute("href");

        if(name != null) {
            document.getElementById("je-link-input").value = name;
        }
        else if(href != null) {
            document.getElementById("je-link-input").value = href;
        }
        else {
            document.getElementById("je-link-input").value = href;
        }

        menu.style.top = top + "px";
        menu.style.left = left + "px";
        menu.style.display = "block";
        this.element = src;
        this.timestamp = new Date().getTime();
    };

    LinkMenu.hide = function(force) {
        if(force != true) {
            var time = new Date().getTime();

            if(time - this.timestamp < 1000) {
                return;
            }
        }
        this.getMenu().style.display = "none";
        this.element = null;
    };

    var CodeMenu = JEditor.CodeMenu = {};

    CodeMenu.getMenu = function() {
        var c = document.getElementById("je-code-menu");

        if(c == null) {
            c = document.createElement("div");
            c.id = "je-code-menu";
            c.className = "je-code-menu";
            c.style.width = "300px";
            c.innerHTML = [
                "<span style=\"margin-right: 8px;\">语言选项:</span>",
                "<select id=\"je-code-language\" class=\"language\">",
                    "<option value=\"\">无</option>",
                    "<option value=\"apache\">Apache</option>",
                    "<option value=\"bash\">Bash</option>",
                    "<option value=\"bat\">Bat</option>",
                    "<option value=\"cs\">C#</option>",
                    "<option value=\"cpp\">C++</option>",
                    "<option value=\"css\">CSS</option>",
                    "<option value=\"coffeescript\">CoffeeScript</option>",
                    "<option value=\"delphi\">Delphi</option>",
                    "<option value=\"diff\">Diff</option>",
                    "<option value=\"go\">Go</option>",
                    "<option value=\"groovy\">Groovy</option>",
                    "<option value=\"html\">HTML</option>",
                    "<option value=\"http\">HTTP</option>",
                    "<option value=\"ini\">INI</option>",
                    "<option value=\"json\">JSON</option>",
                    "<option value=\"java\">Java</option>",
                    "<option value=\"javascript\">JavaScript</option>",
                    "<option value=\"lua\">lua</option>",
                    "<option value=\"makefile\">Makefile</option>",
                    "<option value=\"markdown\">Markdown</option>",
                    "<option value=\"nginx\">Nginx</option>",
                    "<option value=\"objectivec\">Objective-C</option>",
                    "<option value=\"php\">PHP</option>",
                    "<option value=\"perl\">Perl</option>",
                    "<option value=\"python\">Python</option>",
                    "<option value=\"ruby\">Ruby</option>",
                    "<option value=\"scala\">Scala</option>",
                    "<option value=\"scss\">SCSS</option>",
                    "<option value=\"sql\">SQL</option>",
                    "<option value=\"swift\">Swift</option>",
                    "<option value=\"vbscript\">VBScript</option>",
                    "<option value=\"xml\">XML</option>",
                "</select>",
            ].join("");
            document.body.appendChild(c);

            com.skin.util.EventUtil.addListener(document.getElementById("je-code-language"), "change", function() {
                var src = CodeMenu.element;

                if(src != null) {
                    var value = document.getElementById("je-code-language").value;
                    src.setAttribute("je-code-language", value);
                }
            });
        }
        return c;
    };

    CodeMenu.show = function(src, top, left) {
        /**
         * 先更新时间
         */
        this.timestamp = new Date().getTime();

        /**
         * 避免鼠标在当前元素上时重新更新下拉选项
         */
        if(src == this.element) {
            return;
        }

        var menu = this.getMenu();
        var language = src.getAttribute("je-code-language");

        if(language != null) {
            document.getElementById("je-code-language").value = language;
        }
        else {
            document.getElementById("je-code-language").value = "";
        }
        menu.style.top = top + "px";
        menu.style.left = left + "px";
        menu.style.display = "block";
        this.element = src;
    };

    CodeMenu.hide = function(force) {
        if(force != true) {
            var time = new Date().getTime();

            if(time - this.timestamp < 1000) {
                return;
            }
        }

        this.getMenu().style.display = "none";
        this.element = null;
    };

    var ContextMenu = JEditor.ContextMenu = function(editor) {
        this.editor = editor;
    };

    ContextMenu.prototype.show = function(event) {
        var d = document;
        var b = document.body;
        var c = this.getContainer();
        var e = this.editor.getIFrame();

        if(d != null) {
            var top = e.offsetTop + b.scrollTop + event.clientY;
            var left = e.offsetLeft + b.scrollLeft + event.clientX;
            c.style.display = "block";

            if(top + c.offsetHeight > (b.scrollTop + d.documentElement.clientHeight)) {
                top = (top - c.offsetHeight);
            }

            if(top < b.scrollTop) {
                top = b.scrollTop;
            }

            if(left + c.offsetWidth > (b.scrollLeft + d.documentElement.clientWidth)) {
                left = (left - c.offsetWidth);
            }

            if(left < b.scrollLeft) {
                left = b.scrollLeft;
            }
            c.style.top = top + "px";
            c.style.left = left + "px";
            c.style.display = "block";
        }
        return this;
    };

    ContextMenu.prototype.hide = function(event) {
        this.getContainer().style.display = "none";
    };

    ContextMenu.prototype.getParent = function(e, name) {
        if(e == null) {
            return null;
        }

        var p = e;

        while(true) {
            var nodeName = p.nodeName.toLowerCase();

            if(nodeName == name) {
                return p;
            }

            p = p.parentNode;

            if(p == null) {
                break;
            }
        }
        return null;
    };

    ContextMenu.prototype.getContainer = function() {
        var d = document;
        var c = d.getElementById("je-contextmenu");
        var home = JEditor.getHome();

        if(c == null) {
            c = d.createElement("div");
            c.id = "je-contextmenu";
            c.className = "je-ctrl contextmenu";
            c.style.top = "50px";
            c.style.left = "100px";
            c.style.display = "none";
            c.innerHTML = [
                "<ul class=\"menu\">",
                "<li class=\"item\" command=\"back\" unselectable=\"on\">",
                "<span class=\"icon\"><img src=\"" + home + "/images/back.gif\"/></span>",
                "<a class=\"command\" href=\"javascript:void(0)\">返 回</a>",
                "</li>",
                "<li class=\"item\" command=\"refresh\" unselectable=\"on\">",
                "<span class=\"icon\"><img src=\"" + home + "/images/refresh.gif\"/></span>",
                "<a class=\"command\" href=\"javascript:void(0)\">刷 新</a>",
                "</li>",
                "<li class=\"separator\"></li>",
                "<li class=\"item\" command=\"cut\" unselectable=\"on\">",
                "<span class=\"icon\"><img src=\"" + home + "/images/cut.gif\"/></span>",
                "<a class=\"command\" href=\"javascript:void(0)\">剪切(X)</a>",
                "</li>",
                "<li class=\"item\" command=\"copy\" unselectable=\"on\">",
                "<span class=\"icon\"><img src=\"" + home + "/images/copy.gif\"/></span>",
                "<a class=\"command\" href=\"javascript:void(0)\">复制(C)</a>",
                "</li>",
                "<li class=\"item\" command=\"paste\" unselectable=\"on\">",
                "<span class=\"icon\"><img src=\"" + home + "/images/paste.gif\"/></span>",
                "<a class=\"command\" href=\"javascript:void(0)\">粘贴(V)</a>",
                "</li>",
                "<li class=\"item\" command=\"pasteText\" unselectable=\"on\">",
                "<span class=\"icon\"><img src=\"" + home + "/images/paste.gif\"/></span>",
                "<a class=\"command\" href=\"javascript:void(0)\">粘贴纯文本(V)</a>",
                "</li>",
                "<li class=\"separator\"></li>",
                "<li class=\"item\" command=\"remove\" unselectable=\"on\">",
                "<span class=\"icon\"><img src=\"" + home + "/images/delete.gif\"/></span>",
                "<a class=\"command\" href=\"javascript:void(0)\">删除元素(D)</a>",
                "</li>",
                "<li class=\"item\" command=\"ascode\" unselectable=\"on\">",
                "<span class=\"icon\"><img src=\"" + home + "/images/code.gif\"/></span>",
                "<a class=\"command\" href=\"javascript:void(0)\">代码块</a>",
                "</li>",
                "<li class=\"item\" command=\"fmtdiv\" unselectable=\"on\">",
                "<span class=\"icon\"><img src=\"" + home + "/images/div.gif\"/></span>",
                "<a class=\"command\" href=\"javascript:void(0)\">普通块</a>",
                "</li>",
                "<li class=\"item\" command=\"fmtpre\" unselectable=\"on\">",
                "<span class=\"icon\"><img src=\"" + home + "/images/pre.gif\"/></span>",
                "<a class=\"command\" href=\"javascript:void(0)\">已编排格式</a>",
                "</li>",
                "<li class=\"item\" command=\"fmtp\" unselectable=\"on\">",
                "<span class=\"icon\"><img src=\"" + home + "/images/p.gif\"/></span>",
                "<a class=\"command\" href=\"javascript:void(0)\">普通段落</a>",
                "</li>",
                "<li class=\"item\" command=\"anchor\" unselectable=\"on\">",
                "<span class=\"icon\"><img src=\"" + home + "/images/anchor.gif\"/></span>",
                "<a class=\"command\" href=\"javascript:void(0)\">添加锚点(F)</a>",
                "</li>",
                "<li class=\"item\" command=\"insertp\" unselectable=\"on\">",
                "<span class=\"icon\"></span>",
                "<a class=\"command\" href=\"javascript:void(0)\">插入段落(F)</a>",
                "</li>",
                "<li class=\"separator\"></li>",
                "<li class=\"item\" command=\"settop\" unselectable=\"on\">",
                "<span class=\"icon\"></span>",
                "<a class=\"command\" href=\"javascript:void(0)\">设为顶级(F)</a>",
                "</li>",
                "<li class=\"item\" command=\"moveup\" unselectable=\"on\">",
                "<span class=\"icon\"></span>",
                "<a class=\"command\" href=\"javascript:void(0)\">向上一级(F)</a>",
                "</li>",
                "<li class=\"item\" command=\"peel\" unselectable=\"on\">",
                "<span class=\"icon\"></span>",
                "<a class=\"command\" href=\"javascript:void(0)\">去皮儿</a>",
                "</li>",
                "<li class=\"separator\"></li>",
                "<li class=\"item\" command=\"upload-image\" unselectable=\"on\">",
                "<span class=\"icon\"><img src=\"" + home + "/images/img.gif\"/></span>",
                "<a class=\"command\" href=\"javascript:void(0)\">插入图片</a>",
                "</li>",
                "<li class=\"item\" command=\"upload-attach\" unselectable=\"on\">",
                "<span class=\"icon\"><img src=\"" + home + "/images/upload.gif\"/></span>",
                "<a class=\"command\" href=\"javascript:void(0)\">插入附件</a>",
                "</li>",
                "<li class=\"separator\"></li>",
                "<li class=\"item disabled\" unselectable=\"on\">",
                "  <span class=\"icon\"></span>",
                "  <a class=\"command\" href=\"javascript:void(0)\">浏览器菜单: ctrl+右键</a>",
                "</li>",
                "</ul>"].join("");
            d.body.appendChild(c);

            var self = this;
            com.skin.util.EventUtil.addListener(c, "click", function(event) {
                com.skin.util.EventUtil.cancel(event);

                var src = (event.target || event.srcElement);
                var li = self.getParent(src, "li");
                self.hide();

                if(li == null) {
                    return false;
                }

                if(self.execute != null) {
                    setTimeout(function() {
                        self.execute(li, event);
                    }, 0);
                    return true;
                }
                return false;
            });
        }
        return c;
    };
})();

/**
 * table选择
 */
(function() {
    var EventUtil = com.skin.util.EventUtil;
    var StyleUtil = com.skin.util.StyleUtil;

    EventUtil.addListener(window, "load", function(event) {
        var c = JEditor.ToolMenu.getContainer();

        EventUtil.addListener(c, "mouseout", function(event) {
            var src = (event.srcElement || event.target);

            if(src.className.indexOf("je-pick-") < 0) {
                return;
            }

            var info = document.getElementById("je-pick-info");
            var mask = document.getElementById("je-pick-mask");
            mask.style.width = "0px";
            mask.style.height = "0px";
            info.innerHTML = "0 x 0";
        });

        EventUtil.addListener(c, "mousemove", function(event) {
            var src = (event.srcElement || event.target);

            if(src.className.indexOf("je-pick-") < 0) {
                return;
            }

            var y = event.clientY - StyleUtil.getTop(src);
            var x = event.clientX - StyleUtil.getLeft(src);
            var rows = Math.floor((x + 21) / 22);
            var cols = Math.floor((y + 21) / 22);
            var w = rows * 22 - 2;
            var h = cols * 22 - 2;

            var info = document.getElementById("je-pick-info");
            var mask = document.getElementById("je-pick-mask");
            mask.style.width = w + "px";
            mask.style.height = h + "px";
            info.innerHTML = (rows + " x " + cols);
        });

        EventUtil.addListener(c, "click", function(event) {
            var src = (event.srcElement || event.target);

            if(src.className.indexOf("je-pick-mask") < 0) {
                return;
            }

            var y = event.clientY - StyleUtil.getTop(src);
            var x = event.clientX - StyleUtil.getLeft(src);
            var rows = Math.floor((x + 21) / 22);
            var cols = Math.floor((y + 21) / 22);
            JEditor.ToolMenu.execute("table", rows, cols);
        });
    });
})();

/**
 * 工具栏操作
 */
JEditor.tools["save"] = (function() {
    return {
        "name": "save",
        "title": "${tool.save}",
        "execute": function(editor) {
            editor.setEnabled("save", false);

            if(editor.save != null) {
                editor.save();
            }
        }
    };
})();

JEditor.tools["cut"] = (function() {
    return {
        "name": "cut",
        "title": "${tool.cut}",
        "execute": function(editor) {
            try {
                var doc = editor.getDocument();
                if(doc.execCommand("cut"), !doc.queryCommandSupported("cut")) {
                    throw {"name": "UnsupportOperation", "message": "UnsupportOperation"};
                }
            }
            catch(e) {
                alert(com.skin.util.StringUtil.evaluate("${cut.disabled}", this.i18n));
            }
        }
    };
})();

JEditor.tools["copy"] = (function() {
    return {
        "name": "copy",
        "title": "${tool.copy}",
        "execute": function(editor) {
            try{
                editor.setBookmark();
                var doc = editor.getDocument();

                if(doc.execCommand("copy"), !doc.queryCommandSupported("copy")) {
                    throw {"name": "UnsupportOperation", "message": "UnsupportOperation"};
                }
            }
            catch(e) {
                alert(editor.getLang("copy.disabled"));
            }
        }
    };
})();

JEditor.tools["paste"] = (function() {
    return {
        "name": "paste",
        "title": "${tool.paste}",
        "execute": function(editor) {
            if(com.skin.util.Browser.ie) {
                try{
                    editor.setBookmark();
                    var doc = editor.getDocument();

                    if(doc.execCommand("paste"), !doc.queryCommandSupported("paste")) {
                        throw {"name": "UnsupportOperation", "message": "UnsupportOperation"};
                    }
                }
                catch(e) {
                    alert(editor.getLang("paste.disabled"));
                }
            }
            else {
                alert(editor.getLang("paste.disabled"));
            }
        }
    };
})();

JEditor.tools["pasteText"] = (function() {
    return {
        "name": "pasteText",
        "title": "${tool.pasteText}",
        "execute": function(editor) {
            if(com.skin.util.Browser.ie) {
                /*
                try{
                    editor.setBookmark();
                    var doc = editor.getDocument();

                    if(doc.execCommand("paste"), !doc.queryCommandSupported("paste")) {
                        throw {"name": "UnsupportOperation", "message": "UnsupportOperation"};
                    }
                }
                catch(e) {
                    alert(editor.getLang("paste.disabled"));
                }
                */
            }
            else {
                alert(editor.getLang("pasteText.disabled"));
            }
        }
    };
})();

JEditor.tools["bold"] = (function() {
    return {
        "name": "bold",
        "title": "${tool.bold}",
        "execute": function(editor) {
            editor.exec("bold", false);
        }
    };
})();

JEditor.tools["italic"] = (function() {
    return {
        "name": "italic",
        "title": "${tool.italic}",
        "execute": function(editor) {
            editor.exec("italic", false);
        }
    };
})();

JEditor.tools["underline"] = (function() {
    return {
        "name": "underline",
        "title": "${tool.underline}",
        "execute": function(editor) {
            editor.exec("underline", false);
        }
    };
})();

JEditor.tools["strikethrough"] = (function() {
    return {
        "name": "strikethrough",
        "title": "${tool.strikethrough}",
        "execute": function(editor) {
            editor.exec("strikethrough", false);
        }
    };
})();

JEditor.tools["formatBlock"] = (function() {
    return {
        "name": "formatBlock",
        "title": "${tool.formatBlock}",
        "click": function(editor) {
            var m = [
                {"name": "h1"},
                {"name": "h2"},
                {"name": "h3"},
                {"name": "h4"},
                {"name": "h5"},
                {"name": "h6"},
                {"name": "p"},
                {"name": "div"},
                {"name": "blockquote"},
                {"name": "pre"},
                {"name": "address"}
            ];
            var b = ["<div style=\"width: 120px;\">"];

            for(var i = 0; i < m.length; i++) {
                if(i < 6) {
                    b[b.length] = "<a class=\"item\" tabindex=\"0\" title=\"${formatBlock." + m[i].name + "}\" href=\"javascript:void(0)\" command=\"formatBlock\" onclick=\"JEditor.ToolMenu.execute('formatBlock', '" + m[i].name + "');\"><" + m[i].name + ">${formatBlock." + m[i].name + "}</" + m[i].name + "></a>";
                }
                else {
                    b[b.length] = "<a class=\"item\" tabindex=\"0\" title=\"${formatBlock." + m[i].name + "}\" href=\"javascript:void(0)\" command=\"formatBlock\" onclick=\"JEditor.ToolMenu.execute('formatBlock', '" + m[i].name + "');\">${formatBlock." + m[i].name + "}</a>";
                }
            }
            b[b.length] = "</div>";

            var html = com.skin.util.StringUtil.replace(b.join(""), editor.i18n);
            JEditor.ToolMenu.show(editor, "formatBlock", html);
        },
        "execute": function(editor, tag) {
            editor.exec("formatBlock", false, "<" + tag + ">");

            var mark = editor.getMark();
            var range = mark.getRange();
            var node = range.startContainer.parentNode;
            editor.getMark().mark(node);
        }
    };
})();

JEditor.tools["fontName"] = (function() {
    return {
        "name": "fontName",
        "title": "${tool.fontName}",
        "click": function(editor) {
            var m = editor.i18n.fontNameList;
            var b = ["<div style=\"width: 120px;\">"];

            for(var i = 0; i < m.length; i++) {
                m[i].font = (m[i].font || m[i].name);
                b[b.length] = "<a class=\"item\" style=\"font-family: '" + m[i].font + "'\" tabindex=\"0\" title=\"" + m[i].name + "\" href=\"javascript:void(0)\" command=\"fontName\" onclick=\"JEditor.ToolMenu.execute('fontName', '" + m[i].font + "');\">" + m[i].name + "</a>";
            }
            b[b.length] = "</div>";
            JEditor.ToolMenu.show(editor, "fontName", b.join(""));
        },
        "execute": function(editor, tag) {
            editor.exec("fontName", false, tag);
        }
    };
})();

JEditor.tools["fontSize"] = (function() {
    return {
        "name": "fontSize",
        "title": "${tool.fontSize}",
        "click": function(editor) {
            var m = [{"name": "x-small", "size": "10"}, {"name": "small", "size": "12"}, {"name": "medium", "size": "16"}, {"name": "large", "size": "18"}, {"name": "x-large", "size": "24"}, {"name": "xx-large", "size": "32"}, {"name": "-webkit-xxx-large", "size": "48"}];
            var b = ["<div style=\"width: 200px;\">"];

            for(var i = 0; i < m.length; i++) {
                b[b.length] = "<a class=\"item\" style=\"font-size: " + m[i].size + "px;\" tabindex=\"0\" title=\"${fontSize." + m[i].name + "}\" href=\"javascript:void(0)\" command=\"fontSize\" onclick=\"JEditor.ToolMenu.execute('fontSize', '" + (i + 1) + "');\">${fontSize." + m[i].name + "}(" + m[i].size + ")</a>";
            }
            b[b.length] = "</div>";

            var html = com.skin.util.StringUtil.replace(b.join(""), editor.i18n);
            JEditor.ToolMenu.show(editor, "fontSize", html);
        },
        "execute": function(editor) {
            editor.exec("fontSize", false);
        }
    };
})();

JEditor.tools["foreColor"] = (function() {
    return {
        "name": "foreColor",
        "title": "${tool.foreColor}",
        "click": function(editor) {
            JEditor.ToolMenu.showColorMenu(editor, "foreColor");
        },
        "execute": function(editor, color) {
            editor.exec("foreColor", false, color);
        }
    };
})();

JEditor.tools["backColor"] = (function() {
    return {
        "name": "backColor",
        "title": "${tool.backColor}",
        "click": function(editor) {
            JEditor.ToolMenu.showColorMenu(editor, "backColor");
        },
        "execute": function(editor, color) {
            editor.exec("backColor", false, color);
        }
    };
})();

JEditor.tools["selectall"] = (function() {
    return {
        "name": "selectall",
        "title": "${tool.selectall}",
        "execute": function(editor) {
            editor.exec("selectall", false);
        }
    };
})();

JEditor.tools["removeformat"] = (function() {
    return {
        "name": "removeformat",
        "title": "${tool.removeformat}",
        "execute": function(editor) {
            editor.exec("removeformat", false);
        }
    };
})();

JEditor.tools["dedent"] = (function() {
    return {
        "name": "dedent",
        "title": "${tool.dedent}",
        "execute": function(editor) {
            editor.exec("dedent", false);
        }
    };
})();

JEditor.tools["indent"] = (function() {
    return {
        "name": "indent",
        "title": "${tool.indent}",
        "execute": function(editor) {
            editor.exec("indent", false);
        }
    };
})();

JEditor.tools["align"] = (function() {
    return {
        "name": "align",
        "title": "${tool.align}",
        "click": function(editor) {
            var m = ["justifyleft", "justifycenter", "justifyright", "justifyfull"];
            var b = ["<div style=\"width: 60px;\">"];

            for(var i = 0; i < m.length; i++) {
                b[b.length] = "<a class=\"item\" tabindex=\"0\" title=\"${align." + m[i] + "}\" href=\"javascript:void(0)\" command=\"align\" onclick=\"JEditor.ToolMenu.execute('align', '" + m[i] + "');\">${align." + m[i] + "}</a>";
            }
            b[b.length] = "</div>";

            var html = com.skin.util.StringUtil.replace(b.join(""), editor.i18n);
            JEditor.ToolMenu.show(editor, "align", html);
        },
        "execute": function(editor, align) {
            editor.exec(align, false);
        }
    };
})();

JEditor.tools["list"] = (function() {
    return {
        "name": "list",
        "title": "${tool.list}",
        "click": function(editor) {
            var m = ["insertOrderedList", "insertUnorderedList"];
            var b = ["<div style=\"width: 60px;\">"];

            for(var i = 0; i < m.length; i++) {
                b[b.length] = "<a class=\"item\" tabindex=\"0\" title=\"${list." + m[i] + "}\" href=\"javascript:void(0)\" command=\"list\" onclick=\"JEditor.ToolMenu.execute('list', '" + m[i] + "');\">${list." + m[i] + "}</a>";
            }
            b[b.length] = "</div>";

            var html = com.skin.util.StringUtil.replace(b.join(""), editor.i18n);
            JEditor.ToolMenu.show(editor, "list", html);
        },
        "execute": function(editor, list) {
            editor.exec(list, false);
        }
    };
})();

JEditor.tools["hr"] = (function() {
    return {
        "name": "hr",
        "title": "${tool.hr}",
        "execute": function(editor) {
            editor.pasteHtml("<hr/>");
        }
    };
})();

JEditor.tools["unlink"] = (function() {
    return {
        "name": "unlink",
        "title": "${tool.unlink}",
        "execute": function(editor) {
            editor.exec("unlink", false);
        }
    };
})();

JEditor.tools["link"] = (function() {
    return {
        "name": "link",
        "title": "${tool.link}",
        "click": function(editor) {
            var b = [
                "<div class=\"je-menu-form\">",
                    "<div class=\"je-form-row\"><span class=\"je-form-label\">${link.address}:</span><input type=\"text\" name=\"address\" spellcheck=\"false\" value=\"http://\"/></div>",
                    "<div class=\"je-form-row\"><span class=\"je-form-label\">${link.open.type}:</span>",
                        "<select name=\"targetName\">",
                            "<option selected=\"true\" value=\"\">${default.text}</option>",
                            "<option value=\"_blank\">${target.newwindow}</option>",
                            "<option value=\"_self\">${target.self}</option>",
                            "<option value=\"_parent\">${target.parent}</option>",
                        "</select>",
                    "</div>",
                    "<div class=\"je-form-row\"><span class=\"je-form-label\">${link.text}:</span><input type=\"text\" name=\"linkText\" spellcheck=\"false\" value=\"${link.text.value}\"/></div>",
                "</div>",
                "<div class=\"je-form-footer\"><input type=\"button\" value=\"${dialog.ok}\" command=\"link\" onclick=\"JEditor.ToolMenu.execute('link')\"/></div>"];

            var html = com.skin.util.StringUtil.replace(b.join(""), editor.i18n);
            JEditor.ToolMenu.show(editor, "link", html);
        },
        "execute": function(editor) {
            var a = [];
            var bean = JEditor.ToolMenu.getForm();
            bean.address = com.skin.util.StringUtil.trim(bean.address);

            if(com.skin.util.StringUtil.startsWith(bean.address, "http://") == false && com.skin.util.StringUtil.startsWith(bean.address, "https://") == false) {
                bean.address = "http://" + bean.address;
            }

            a[a.length] = "<a href=\"" + bean.address + "\"";

            if(bean.targetName == "_blank" || bean.targetName == "_parent") {
                a[a.length] = " target=\"" + bean.targetName + "\"";
            }

            a[a.length] = ">";

            if(bean.linkText != "") {
                a[a.length] = bean.linkText;
            }

            a[a.length] = "</a>";
            editor.pasteHtml(a.join(""));
        }
    };
})();

JEditor.tools["anchor"] = (function() {
    return {
        "name": "anchor",
        "title": "${tool.anchor}",
        "click": function(editor) {
            var b = [
                "<div class=\"je-menu-form\">",
                    "<div class=\"je-form-row\"><span style=\"padding-right: 10px;\">${anchor.name}:</span><input type=\"text\" name=\"name\" spellcheck=\"false\" value=\"\"/></div>",
                "</div>",
                "<div class=\"je-form-footer\"><input type=\"button\" value=\"${dialog.ok}\" command=\"anchor\" onclick=\"JEditor.ToolMenu.execute('anchor')\"/></div>"];

            var html = com.skin.util.StringUtil.replace(b.join(""), editor.i18n);
            JEditor.ToolMenu.show(editor, "anchor", html);
        },
        "execute": function(editor) {
            var bean = JEditor.ToolMenu.getForm();
            editor.pasteHtml(["<a name=\"", bean.name, "\" class=\"je-anchor\"></a>"].join(""));
        }
    };
})();

JEditor.tools["image"] = (function() {
    return {
        "name": "image",
        "title": "${tool.image}",
        "click": function(editor) {
            var b = [
                "<div class=\"je-menu-form\">",
                    "<div class=\"je-form-row\"><span class=\"je-form-label\">${image.url}:</span><input type=\"text\" name=\"address\" spellcheck=\"false\" value=\"http://\"/></div>",
                    "<div class=\"je-form-row\"><span class=\"je-form-label\">${image.alt}:</span><input type=\"text\" name=\"altText\" spellcheck=\"false\"/></div>",
                    "<div class=\"je-form-row\"><span class=\"je-form-label\">${image.align}:</span><select name=\"align\">",
                        "<option selected=\"selected\" value=\"\">${default.text}</option>",
                        "<option value=\"left\">${image.alignLeft}</option>",
                        "<option value=\"right\">${image.alignRight}</option>",
                        "<option value=\"top\">${image.alignTop}</option>",
                        "<option value=\"center\">${image.alignCenter}</option>",
                        "<option value=\"baseline\">${image.alignBaseline}</option>",
                        "<option value=\"bottom\">${image.alignBottom}</option>",
                    "</select></div>",
                    "<div class=\"je-form-row\">",
                        "<span class=\"je-form-label\">${image.width}:</span><input type=\"text\" name=\"width\" style=\"width: 40px;\" spellcheck=\"false\" value=\"\"/>",
                        "<span class=\"je-form-label\">${image.height}:</span><input type=\"text\" name=\"height\" style=\"width: 40px;\" spellcheck=\"false\"/>",
                    "</div>",
                    "<div class=\"je-form-row\">",
                        "<span class=\"je-form-label\">${image.hspace}:</span><input type=\"text\" name=\"hspace\" style=\"width: 40px;\" spellcheck=\"false\"/>",
                        "<span class=\"je-form-label\">${image.vspace}:</span><input type=\"text\" name=\"vspace\" style=\"width: 40px;\" spellcheck=\"false\"/>",
                    "</div>",
                "</div>",
                "<div class=\"je-form-footer\">",
                    "<input type=\"button\" command=\"upload\" onclick=\"JEditor.upload();\" value=\"${image.upload}\"/>",
                    "<input type=\"button\" value=\"${dialog.ok}\" command=\"img\" onclick=\"JEditor.ToolMenu.execute('image')\"/>",
                "</div>"];

            var html = com.skin.util.StringUtil.replace(b.join(""), editor.i18n);
            JEditor.ToolMenu.show(editor, "image", html);
        },
        "execute": function(editor) {
            var bean = JEditor.ToolMenu.getForm();
            var temp = "<img src=\"${address}\" alt=\"${altText}\" align=\"${align}\" width=\"${width}\" height=\"${height}\" vspace=\"${vspace}\" hspace=\"${hspace}\"/>";
            editor.pasteHtml(com.skin.util.StringUtil.replace(temp, bean));
        }
    };
})();

JEditor.tools["flash"] = (function() {
    return {
        "name": "flash",
        "title": "${tool.flash}",
        "click": function(editor) {
            var b = [
                "<div class=\"je-menu-form\">",
                    "<div class=\"je-form-row\"><span class=\"je-form-label\">${flash.url}:</span><input type=\"text\" name=\"address\" spellcheck=\"false\" value=\"http://\"/></div>",
                    "<div class=\"je-form-row\"><span class=\"je-form-label\">${flash.width}:</span><input type=\"text\" name=\"width\" style=\"width: 40px;\" spellcheck=\"false\" value=\"600\"/></div>",
                    "<div class=\"je-form-row\"><span class=\"je-form-label\">${flash.height}:</span><input type=\"text\" name=\"height\" style=\"width: 40px;\" spellcheck=\"false\" value=\"480\"/></div>",
                "</div>",
                "<div class=\"je-form-footer\"><input type=\"button\" value=\"${dialog.ok}\" command=\"flash\" onclick=\"JEditor.ToolMenu.execute('flash')\"/></div>"];

            var html = com.skin.util.StringUtil.replace(b.join(""), editor.i18n);
            JEditor.ToolMenu.show(editor, "flash", html);
        },
        "execute": function(editor) {
            var bean = JEditor.ToolMenu.getForm();
            var temp = "<embed type=\"application/x-shockwave-flash\" classid=\"clsid:d27cdb6e-ae6d-11cf-96b8-4445535400000\" src=\"${address}\" wmode=\"opaque\" quality=\"high\" menu=\"false\" play=\"true\" loop=\"true\" allowfullscreen=\"true\" width=\"${width}\" height=\"${height}\"/>";
            editor.pasteHtml(com.skin.util.StringUtil.replace(temp, bean));
        }
    };
})();

JEditor.tools["media"] = (function() {
    return {
        "name": "media",
        "title": "${tool.media}",
        "click": function(editor) {
            var b = [
                "<div class=\"je-menu-form\">",
                    "<div class=\"je-form-row\"><span class=\"je-form-label\">${media.url}:</span><input type=\"text\" name=\"address\" spellcheck=\"false\" value=\"http://\"></div>",
                    "<div class=\"je-form-row\"><span class=\"je-form-label\">${media.width}:</span><input type=\"text\" name=\"width\" style=\"width: 40px;\" value=\"600\"/></div>",
                    "<div class=\"je-form-row\"><span class=\"je-form-label\">${media.height}:</span><input type=\"text\" name=\"height\" value=\"480\"/></div>",
                "</div>",
                "<div class=\"je-form-footer\"><input type=\"button\" value=\"${dialog.ok}\" command=\"media\" onclick=\"JEditor.ToolMenu.execute('media')\"/></div>"];

            var html = com.skin.util.StringUtil.replace(b.join(""), editor.i18n);
            JEditor.ToolMenu.show(editor, "media", html);
        },
        "execute": function(editor) {
            var bean = JEditor.ToolMenu.getForm();
            var temp = "<embed type=\"application/x-mplayer2\" classid=\"clsid:6bf52a52-394a-11d3-b153-00c04f79faa6\" src=\"${address}\" enablecontextmenu=\"false\" autostart=\"false\" width=\"${width}\" height=\"height\"/>";
            editor.pasteHtml(com.skin.util.StringUtil.replace(temp, bean));
        }
    };
})();

JEditor.tools["emot"] = (function(image) {
    return {
        "name": "emot",
        "title": "${tool.emot}",
        "click": function(editor) {
            var b = [];
            var c = [];
            var p = Math.floor((135 + 27) / 28);
            var home = JEditor.getHome();

            for(var i = 0; i < 135; i++) {
                c[i] = i;
            }

            for(var i = 0; i < p; i++) {
                if(i < 1) {
                    b[b.length] = "<div pageId=\"" + (i + 1) + "\">\r\n";
                }
                else {
                    b[b.length] = "<div pageId=\"" + (i + 1) + "\"style=\"display: none;\">\r\n";
                }

                for(var j = 0; j < 4; j++) {
                    b[b.length] = "<div class=\"je-emot-panel\">";

                    for(var k = 0; k < 7; k++) {
                        var m = i * 28 + j * 7 + k;

                        if(m < c.length) {
                            b[b.length] = "<a href=\"javascript:void(0)\"><img src=\"" + home + "/emot/" + c[m] + ".gif\" command=\"emot\" onclick=\"JEditor.ToolMenu.execute('emot', '" + home + "/emot/" + c[m] + ".gif')\"/></a>";
                        }
                    }
                    b[b.length] = "</div>\r\n";
                }
                b[b.length] = "</div>\r\n";
            }

            if(p > 1) {
                b[b.length] = "<div class=\"pagebar\">";

                for(var i = 0; i < p; i++) {
                    if(i < 1) {
                        b[b.length] = "<span class=\"active\" pageId=\"" + (i + 1) + "\" onclick=\"JEditor.ScrollPage.scroll(this)\">" + (i + 1) + "</span>";
                    }
                    else {
                        b[b.length] = "<span pageId=\"" + (i + 1) + "\" onclick=\"JEditor.ScrollPage.scroll(this)\">" + (i + 1) + "</span>";
                    }
                }
                b[b.length] = "</div>";
            }

            var html = com.skin.util.StringUtil.replace(b.join(""), editor.i18n);
            JEditor.ToolMenu.show(editor, "emot", html);
        },
        "execute": function(editor, image) {
            editor.pasteHtml("<img src=\"" + image + "\" emot=\"true\"/>");
        }
    };
})();

JEditor.tools["table"] = (function() {
    return {
        "name": "table",
        "title": "${tool.table}",
        "click": function(editor) {
            var b = [
                "<div id=\"je-pick-info\" class=\"je-form-row\">0 x 0</div>",
                "<div class=\"je-pick-area\"><div id=\"je-pick-mask\" class=\"je-pick-mask\"></div></div>"];

            var html = com.skin.util.StringUtil.replace(b.join(""), editor.i18n);
            JEditor.ToolMenu.show(editor, "table", html);
        },
        "execute": function(editor, rows, cols) {
            var b = [];
            b[b.length] = "<table>";

            for(var i = 0; i < rows; i++) {
                b[b.length] = "<tr>";

                for(var j = 0; j < cols; j++) {
                    b[b.length] = "<td>&nbsp;</td>";
                }
                b[b.length] = "</tr>";
            }
            b[b.length] = "</table>";
            editor.pasteHtml(b.join(""));
        }
    };
})();

JEditor.tools["source"] = (function() {
    return {
        "name": "source",
        "title": "${tool.source}",
        "execute": function(editor) {
            editor.toggle();
        }
    };
})();

JEditor.tools["fullscreen"] = (function() {
    return {
        "name": "fullscreen",
        "title": "${tool.fullscreen}",
        "execute": function(editor) {
            var c = editor.getContainer();

            if(c.getAttribute("mode") != "1") {
                com.skin.util.StyleUtil.addClass(document.documentElement, "html_fullsrceen");
                com.skin.util.StyleUtil.addClass(c, "fullscreen");
                c.setAttribute("mode", "1");
                editor.resize();
            }
            else {
                com.skin.util.StyleUtil.removeClass(document.documentElement, "html_fullsrceen");
                com.skin.util.StyleUtil.removeClass(c, "fullscreen");
                c.setAttribute("mode", "0");
                editor.resize();
            }
        }
    };
})();

JEditor.tools["print"] = (function() {
    return {
        "name": "print",
        "title": "${tool.print}",
        "execute": function(editor) {
            editor.print();
        }
    };
})();

JEditor.tools["about"] = (function() {
    return {
        "name": "about",
        "title": "${tool.about}",
        "click": function(editor) {
            var b = [
                "<div class=\"je-menu-form\">",
                    "<div class=\"je-about\" tabindex=\"-1\"><span style=\"font-size: 20px; color: #1997df;\">JEditor</span></div>",
                    "<div class=\"je-form-row\">v" + JEditor.version + " (build 110110)</div>",
                "</div>",
                "<div class=\"je-form-footer\"></div>"];

            var html = com.skin.util.StringUtil.replace(b.join(""), editor.i18n);
            JEditor.ToolMenu.show(editor, "about", html);
        }
    };
})();

/**
 * 工具栏单击
 */
JEditor.plugin({name: "je-plugin1", "execute": function(editor) {
    var toolbar = editor.getToolbar();
    var EventUtil = com.skin.util.EventUtil;
    var StyleUtil = com.skin.util.StyleUtil;

    EventUtil.addListener(window, "resize", function(event) {
        editor.resize();
    });

    EventUtil.addListener(toolbar, "click", function(event) {
        var src = (event.srcElement || event.target);
        var name = src.getAttribute("command");

        if(name == null) {
            return false;
        }

        if(StyleUtil.hasClass(src, "disabled")) {
            return false;
        }

        var command = JEditor.tools[name];

        if(command == null) {
            return false;
        }

        if(command.click != null) {
            command.click(editor);
            return true;
        }

        if(command.execute != null) {
            command.execute(editor);
            return true;
        }
        return false;
    });
}});

JEditor.plugin({name: "je-plugin2", "execute": function(editor) {
    var iframe = editor.getIFrame();
    var doc = editor.getDocument();
    var dombar = editor.getDombar();
    var domLock = document.getElementById(editor.domLockId);

    var CodeMenu = JEditor.CodeMenu;
    var LinkMenu = JEditor.LinkMenu;
    var ToolMenu = JEditor.ToolMenu;

    var DOM = com.skin.util.DOM;
    var KeyCode = com.skin.util.KeyCode
    var EventUtil = com.skin.util.EventUtil;
    var StyleUtil = com.skin.util.StyleUtil;

    /**
     * menu
     */
    EventUtil.addListener(doc, "scroll", function(event) {
        ToolMenu.hide(true);
        LinkMenu.hide(true);
        CodeMenu.hide(true);
    });

    EventUtil.addListener(doc.body, "mouseover", function(event) {
        var src = (event.srcElement || event.target);
        var nodeName = src.nodeName.toLowerCase();

        if(nodeName == "body" || nodeName == "textarea" || nodeName == "html") {
            LinkMenu.hide();
            return true;
        }

        if(nodeName == "a") {
            var top = editor.getOffsetTop(src) - 74;
            var left = editor.getOffsetLeft(src);

            try {
                CodeMenu.hide(true);
                LinkMenu.show(src, top, left);
            }
            catch(e) {
                console.log(e.name + ": " + e.message);
            }
        }
    });

    EventUtil.addListener(doc, "click", function(event) {
        var src = (event.srcElement || event.target);
        var nodeName = src.nodeName.toLowerCase();
        LinkMenu.hide(true);
        ToolMenu.hide(true);
        editor.getContextMenu().hide();

        if(nodeName == "pre") {
            var top = editor.getOffsetTop(src) - 74;
            var left = editor.getOffsetLeft(src);

            if(top > 0 && left > 0) {
                CodeMenu.show(src, top, left);
            }
        }
        else {
            CodeMenu.hide(true);
        }

        if(event.ctrlKey) {
            src = DOM.getTop(src);
        }

        var mark = editor.getMark();
        var node = mark.getCurrent(src);

        if(mark.mark(node) == null) {
            var range = mark.getRange();

            if(range != null) {
                node = mark.getCurrent(range.startContainer);
                mark.mark(node);
            }
        }
    });

    EventUtil.addListener(domLock, "click", function(event) {
        var src = (event.srcElement || event.target);
        var checked = src.getAttribute("checked");

        if(checked == "1") {
            src.className = "checkbox";
            src.setAttribute("checked", "0");
        }
        else {
            src.className = "checkbox checked";
            src.setAttribute("checked", "1");
        }
    });

    EventUtil.addListener(dombar, "click", function(event) {
        var src = (event.srcElement || event.target);

        if(src.className != "je-tag") {
            return;
        }

        var nodeName = src.innerHTML;
        var level = parseInt(src.getAttribute("level"));

        if(nodeName == "body" || nodeName == "html") {
            return;
        }

        if(isNaN(level) || level == 0) {
            return;
        }

        var mark = editor.getMark();
        var e = mark.getElement();

        if(e == null) {
            return;
        }

        for(var i = 0; i < level; i++) {
            if((e = e.parentNode) == null) {
                break;
            }
        }

        if(e == null) {
            return;
        }
        mark.mark(e);
    });

    EventUtil.addListener(doc, "keyup", function(event) {
        editor.getMark().show();
    });

    EventUtil.addListener(doc, "paste", function(event) {
        ToolMenu.hide(true);
        var clipboard = (event.clipboardData || window.clipboardData);
        var items = clipboard.items;

        if(items == null || items.length < 1) {
            return true;
        }

        var kind = "";

        for(var i = 0, length = items.length; i < length; i++) {
            var kind = items[i].kind;

            console.log("kind: " + kind);

            if(kind == "string") {
                break;
            }
        }

        if(kind != "string") {
            return true;
        }

        if(event.shiftKey == true) {
            var text = clipboard.getData("text/plain");
            clipboard.setData("text/plain", text);
        }
        return true;
    });

    EventUtil.addListener(doc, "paste", function(event) {
        ToolMenu.hide(true);
        var clipboard = (event.clipboardData || window.clipboardData);
        var items = clipboard.items;

        if(items == null || items.length < 1) {
            return true;
        }

        if(editor.uploader == null) {
            return false;
        }

        for(var i = 0, length = items.length; i < length; i++) {
            var item = items[i];

            if(item.kind == "file" || item.type.indexOf("image") > -1) {
                var file = item.getAsFile();
                file.name = "blob." + item.type.replace("image/", "");
                editor.uploader.select([file]);
            }
        }
        return false;
    });

    /**
     * drop support
     */
    EventUtil.addListener(doc, "drop", function(event) {
        event.preventDefault();
        editor.uploader.select(event.dataTransfer.files);
    });

    EventUtil.addListener(doc, "contextmenu", function(event) {
        ToolMenu.hide(true);
        CodeMenu.hide(true);
        LinkMenu.hide(true);

        if(editor.mode == 2) {
            return true;
        }

        var keyCode = (event.keyCode || event.which);

        if(event.ctrlKey) {
            return true;
        }

        var domLock = editor.getDomLock();
        var src = (event.srcElement || event.target);

        if(domLock != true) {
            editor.getMark().mark(src);
        }

        editor.getContextMenu().show(event);
        EventUtil.cancel(event);
        return true;
    });

    EventUtil.addListener(doc, "keydown", function(event) {
        var keyCode = (event.keyCode || event.which);

        if(event.ctrlKey) {
            var c = String.fromCharCode(keyCode);

            if(c == "A" || c == "C" || c == "V" || c == "X") {
                return true;
            }

            var command = editor.shortcuts["Ctrl+" + c];

            if(command != null) {
                var plugin = editor.getPlugin(command);

                if(plugin != null) {
                    var tool = editor.getTool(command);

                    if(plugin.mouseover != null) {
                        plugin.mouseover.call(this, tool);
                    }
                    else if(plugin.execute != null) {
                        plugin.execute.call(this, command);
                    }
                }
                EventUtil.cancel(event);
                return false;
            }
            return true;
        }
        else {
            switch(keyCode) {
                case KeyCode.DELETE:
                case KeyCode.BACKSPACE: {
                    return true;
                }
                case KeyCode.ENTER: {
                    if(editor.mode == 2) {
                        return true;
                    }

                    var mark = editor.getMark();
                    var e = mark.getElement();

                    if(e == null) {
                        return true;
                    }

                    if(mark.getParent("pre") == null) {
                        return true;
                    }
                    editor.pasteHtml("\r\n");
                    EventUtil.cancel(event);
                    return false;
                }
            }
            return true;
        }
    });
}});

JEditor.plugin({name: "je-contextmenu", "execute": function(editor) {
    editor.getContextMenu = function() {
        /**
         * 菜单操作已经太多了，以后再重构吧
         * TODO: 针对不同的元素显示不同的菜单
         */
        if(this.contextMenu == null) {
            var self = this;
            var DOM = com.skin.util.DOM;

            this.contextMenu = new JEditor.ContextMenu(this);
            this.contextMenu.execute = function(src, event) {
                var command = src.getAttribute("command");

                if(command == "remove") {
                    var mark = self.getMark();
                    var e = mark.getElement();

                    if(e == null) {
                        return true;
                    }

                    var node = DOM.next(e);

                    if(node == null) {
                        node = DOM.prev(e);
                    }

                    e.parentNode.removeChild(e);
                    DOM.clear(self.getBody());
                    mark.mark(node);
                }
                else if(command == "ascode") {
                    var mark = self.getMark();
                    var e = mark.getElement();

                    /**
                     * 当前持有的element可能已经从当前文档中删除了
                     */
                    if(e == null || e.parentNode == null) {
                        mark.hide();
                        return true;
                    }

                    var txt = e.innerText;
                    var doc = self.getDocument();
                    var nodeName = e.nodeName.toLowerCase();

                    if(nodeName == "tr" || nodeName == "img") {
                        return;
                    }

                    /**
                     * 1. 删除行尾空格
                     * 2. 清除多余换行
                     */
                    txt = txt.replace(/ /g, " ");
                    txt = txt.replace(/[ ]*\n/g, "\n");
                    txt = txt.replace(/&nbsp;/g, " ");
                    txt = txt.replace(/<br\/>/g, "\n");

                    if(nodeName == "pre") {
                        e.innerHTML = "";
                        e.appendChild(doc.createTextNode(txt));
                        return;
                    }

                    var pre = document.createElement("pre");
                    pre.appendChild(doc.createTextNode(txt));

                    if(nodeName == "tbody") {
                        e = DOM.getParent(e, "table");
                        nodeName = "table";
                    }

                    if(nodeName == "table" || nodeName == "ul" || nodeName == "ol" || nodeName == "dl") {
                        var parent = e.parentNode;
                        parent.insertBefore(pre, e);
                        parent.removeChild(e);
                        mark.mark(pre);
                        return;
                    }

                    e.innerHTML = "";
                    e.appendChild(pre);
                    mark.mark(e);
                }
                else if(command == "fmtp") {
                    self.exec("formatBlock", false, "<p>");
                    self.getMark().show();
                }
                else if(command == "fmtdiv") {
                    self.exec("formatBlock", false, "<div>");
                    self.getMark().show();
                }
                else if(command == "fmtpre") {
                    self.exec("formatBlock", false, "<pre>");
                    self.getMark().show();
                }
                else if(command == "insertp") {
                    var mark = self.getMark();
                    var doc = self.getDocument();
                    var ele = mark.getElement();

                    if(ele == null) {
                        return;
                    }

                    var p = document.createElement("p");
                    p.appendChild(document.createElement("br"));
                    ele.parentNode.insertBefore(p, ele);
                    mark.mark(p);
                }
                else if(command == "peel") {
                    /**
                     * 去皮儿
                     */
                    var mark = self.getMark();
                    var e = mark.getElement();

                    if(e == null) {
                        console.log("mark.element is null.");
                        mark.hide();
                        return;
                    }

                    var doc = self.getDocument();

                    while(true) {
                        var nodeName = e.nodeName.toLowerCase();

                        if(nodeName == "table" || nodeName == "tbody" || nodeName == "tr" || nodeName == "td"
                            || nodeName == "ul" || nodeName == "ol" || nodeName == "dl" || nodeName == "li" || nodeName == "dd") {
                            return;
                        }

                        if(nodeName == "img") {
                            e = e.parentNode;
                        }
                        else {
                            break;
                        }

                        if(e == null) {
                            break;
                        }
                    }

                    var list = [];
                    var parent = e.parentNode;
                    var childNodes = e.childNodes;
                    var fragment = doc.createDocumentFragment();

                    for(var i = 0;  i < childNodes.length; i++) {
                        list[list.length] = childNodes[i];
                    }

                    for(var i = 0;  i < list.length; i++) {
                        var node = list[i];
                        e.removeChild(node);
                        fragment.appendChild(node);
                    }

                    parent.insertBefore(fragment, e);
                    parent.removeChild(e);
                    mark.mark(parent);
                }
                else if(command == "settop") {
                    /**
                     * 设为顶级元素, 仅次于body
                     */
                    var mark = self.getMark();
                    var doc = self.getDocument();
                    var ele = DOM.movetop(self.getDocument(), mark.getElement());

                    if(ele == null) {
                        mark.hide(ele);
                    }
                    else {
                        /**
                         * firefox下刚刚移动的节点宽高都为0
                         * 需要等待一会再执行清除
                         */
                        setTimeout(function() {
                            DOM.clear(doc.body);
                            mark.mark(ele);
                        }, 200);
                    }
                }
                else if(command == "moveup") {
                    /**
                     * 向上一级
                     */
                    var mark = self.getMark();
                    var doc = self.getDocument();
                    var ele = DOM.moveup(self.getDocument(), mark.getElement());

                    if(ele == null) {
                        mark.hide(ele);
                    }
                    else {
                        mark.mark(ele);
                    }
                }
                else if(command == "upload-image") {
                    if(self.uploader != null) {
                        self.uploader.open();
                    }
                }
                else if(command == "upload-attach") {
                    if(self.uploader != null) {
                        self.uploader.open();
                    }
                }
                else if(command == "refresh") {
                    window.location.reload();
                }
                else if(command == "back") {
                    window.history.back();
                }
                else {
                    self.dispatch(command);
                }
            };
        }
        return this.contextMenu;
    };
}});

(function() {
    /**
     * 注: JEditor并不依赖于jQuery, 这里只是提供一种简便的创建JEditor的方法.
     * 如果你使用了jQuery, 只需要使用jQuery("#my_textarea_id").jeditor()即可.
     */
    if(typeof(jQuery) != null && typeof(jQuery) != "undefined") {
        jQuery.fn.extend({
            jeditor: function() {
                jQuery(this).each(function() {
                    var textarea = jQuery(this);
                    var width = textarea.width();
                    var height = textarea.height();

                    var jeditor = new JEditor.Editor();
                    var id = "jeditor_inst_" + jeditor.id;
                    var toolbar = textarea.attr("toolbar");
                    var theme = textarea.attr("theme");

                    textarea.hide();
                    textarea.after("<div id=\"" + id + "\" style=\"height: 100%;\"></div>");

                    var options = {target: id, html: textarea.val()};

                    if(toolbar != null) {
                        options.toolbar = toolbar;
                    }

                    if(theme != null) {
                        options.theme = theme;
                    }

                    textarea.attr("editorId", jeditor.instanceId);
                    jeditor.create(options);
                });
            },
            fullscreen: function() {
                var textarea = jQuery(this).get(0);
                var instance = JEditor.getInstance(textarea);
                instance.fullscreen();
            }
        });
    }
})();

